Set-up packages // libraries and prepare for data import:
## Uncomment install.packages and run outside of notebook environment:
## install.packages(c("psych" ,"xtable", "tidyverse", "jsonlite", "likert", "ggplot2", "ploty", "mosaic", "modelr", "broom"))
library(psych)
library(likert)
Loading required package: ggplot2
Attaching package: ‘ggplot2’
The following objects are masked from ‘package:psych’:
%+%, alpha
Loading required package: xtable
library(jsonlite)
library(ggplot2)
library(plotly)
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library(modelr)
Attaching package: ‘modelr’
The following object is masked from ‘package:psych’:
heights
library(broom)
Attaching package: ‘broom’
The following object is masked from ‘package:modelr’:
bootstrap
source("http://pcwww.liv.ac.uk/~william/R/crosstab.r")
theme_set(theme_classic())
Set-up directories, import and clean data:
rm(list=ls())
setwd("/Users/allieblaising/desktop/bang/R")
getwd()
[1] "/Users/allieblaising/Desktop/bang/R"
dataPath = "../.data"
## Define function to extract survey results:
extractSurvey = function(frame,survey) {
rounds = seq(1,length(frame$results.format[[1]]))
roundResponses = lapply(rounds, function(round) {
getCol = paste("results.",survey,".",round, sep="")
surveyCols = Filter(function(x) grepl(getCol,x),names(frame))
newCols = lapply(surveyCols, function(x) gsub(getCol,paste("results.",survey, sep=""),x) )
surveyFrame = frame[,surveyCols]
if (is.null(newCols)) {return("No newCols")}
names(surveyFrame) = newCols
surveyFrame$id = frame$id
surveyFrame$round = round
surveyFrame$batch = frame$batch
surveyFrame$rooms = frame$rooms
surveyFrame$manipulation = frame$results.manipulationCheck
surveyFrame$blacklist = frame$results.blacklistCheck
return(surveyFrame)
})
return(Reduce(rbind, roundResponses))
}
#Find directory for import (be sure to verify that batch #s align from bangData import and imports below):
batches = dir(dataPath, pattern = "^[0-9]+$" )
completeBatches = Filter(function(batch) {
if (any(dir(paste(dataPath,batch,sep="/")) == "batch.json") && (any(dir(paste(dataPath,batch,sep="/")) == "users.json")) ) {
batchData = read_json(paste(dataPath,batch,"batch.json",sep="/"), simplifyVector = TRUE)
return(any(batchData$batchComplete == TRUE))
}
return(FALSE)
}, batches)
userFiles = lapply(completeBatches, function(batch) {
userFile = read_json(paste(dataPath,batch,"users.json",sep="/"), simplifyVector=TRUE)
return(flatten(userFile, recursive = TRUE))
})
## Retroactively find rooms from chat data:
overlappingFiles = Reduce(function(x,y) merge(x, y, all=TRUE), userFiles)
roundsWithRooms = apply(overlappingFiles,1,function(x) {
roomsForIndividual = lapply(seq(1,3),function(y) {
x$room = x$rooms[y]
x$round = y
return(x)
})
return(Reduce(rbind, roomsForIndividual))
})
library(tidyverse)
[30m── [1mAttaching packages[22m ────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──[39m
[30m[32m✔[30m [34mtibble [30m 1.4.2 [32m✔[30m [34mpurrr [30m 0.2.5
[32m✔[30m [34mtidyr [30m 0.8.1 [32m✔[30m [34mdplyr [30m 0.7.6
[32m✔[30m [34mreadr [30m 1.1.1 [32m✔[30m [34mstringr[30m 1.3.1
[32m✔[30m [34mtibble [30m 1.4.2 [32m✔[30m [34mforcats[30m 0.3.0[39m
[30m── [1mConflicts[22m ───────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
[31m✖[30m [34mggplot2[30m::[32m%+%()[30m masks [34mpsych[30m::%+%()
[31m✖[30m [34mggplot2[30m::[32malpha()[30m masks [34mpsych[30m::alpha()
[31m✖[30m [34mbroom[30m::[32mbootstrap()[30m masks [34mmodelr[30m::bootstrap()
[31m✖[30m [34mdplyr[30m::[32mfilter()[30m masks [34mplotly[30m::filter(), [34mstats[30m::filter()
[31m✖[30m [34mpurrr[30m::[32mflatten()[30m masks [34mjsonlite[30m::flatten()
[31m✖[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()
[31m✖[30m [34mdplyr[30m::[32mrecode()[30m masks [34mlikert[30m::recode()[39m
library(mosaic)
Loading required package: lattice
Loading required package: ggformula
New to ggformula? Try the tutorials:
learnr::run_tutorial("introduction", package = "ggformula")
learnr::run_tutorial("refining", package = "ggformula")
Attaching package: ‘ggformula’
The following object is masked from ‘package:modelr’:
na.warn
Loading required package: mosaicData
Loading required package: Matrix
Attaching package: ‘Matrix’
The following object is masked from ‘package:tidyr’:
expand
The 'mosaic' package masks several functions from core packages in order to add
additional features. The original behavior of these functions should not be affected by this.
Note: If you use the Matrix package, be sure to load it BEFORE loading mosaic.
Attaching package: ‘mosaic’
The following object is masked from ‘package:Matrix’:
mean
The following objects are masked from ‘package:dplyr’:
count, do, tally
The following object is masked from ‘package:purrr’:
cross
The following object is masked from ‘package:modelr’:
resample
The following object is masked from ‘package:plotly’:
do
The following object is masked from ‘package:ggplot2’:
stat
The following objects are masked from ‘package:psych’:
logit, read.file, rescale
The following objects are masked from ‘package:stats’:
binom.test, cor, cor.test, cov, fivenum, IQR, median, prop.test, quantile, sd, t.test, var
The following objects are masked from ‘package:base’:
max, mean, min, prod, range, sample, sum
## To filter the right batch numbers, add the first batch number for our runs (i.e. batch >= "first batch #")
## overlappingFiles <- overlappingFiles %>% filter(batch=="1536132233074")
More cleaning before visualizations:
## Apply extract survey function to extract the right columns and rows for viability survey:
# overlappingFiles <- overlappingFiles %>% filter(batch>="1536276904547")
# qFifteen <- as.data.frame(extractSurvey(overlappingFiles, 'qFifteenCheck'))
# qSixteen <- as.data.frame(extractSurvey(overlappingFiles, 'qSixteenCheck'))
# viabilitySurvey <- as.data.frame(extractSurvey(overlappingFiles, 'viabilityCheck'))
# qFifteen <- qFifteen %>% select(id, results.qFifteenCheck)
# qSixteen <- qSixteen %>% select(id, results.qSixteenCheck)
# qFifteen$id <- unlist(qFifteen$id)
# qSixteen$id <- unlist(qSixteen$id)
# postSurveyQs <- cbind(qFifteen, qSixteen)
# frame <- cbind(viabilitySurvey, postSurveyQs)
# frame <- frame[, !duplicated(colnames(frame))]
frame <- extractSurvey(overlappingFiles, 'viabilityCheck')
## Reduce to vertically combine rows in roundwithRooms list:
finalRounds = as.data.frame(Reduce(rbind,roundsWithRooms))
## Subset incomplete cases from viability survey dataframe, use manipulation check b/c required for complete observation:
data <- frame[frame$manipulation!="",]
## Rename room to rooms so that both are retained in future merge:
data <- rename(data, rooms = "rooms")
## Subset incomplete cases for final rounds dataframe:
data2 <- finalRounds[finalRounds$results.manipulationCheck!="", ]
## Select only variables of interest from final rounds:
data2 = data2 %>% select(id, batch, room, bonus, name, friends,
friends_history, results.condition, results.format,
results.manipulation,results.manipulationCheck,results.blacklistCheck, round)
## Convert to compatible data types before merge (**this should be simplified**)
data2$batch <- unlist(data2$batch)
data2$round <- unlist(data2$round)
data2$id <- unlist(data2$id)
data$batch <- unlist(data$batch)
## Before merge, data and data2 should have the same # of observations
## Merge columns by id, round and batch #s:
data <- left_join(data, data2, by=NULL)
Joining, by = c("id", "round", "batch")
## Subset only observations with batch #s in complete batches
allConditions <- data[data$batch %in% completeBatches, ]
Conditionally assign conditions based on treatment and results column:
## Messy, but robust? Verify, verify, verify people:
data <- data %>% mutate(
condition = case_when(
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='control' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='baseline' & results.format=="1:3" & round==1 ~ "A" ,
results.condition=='baseline' & results.format=="1:3" & round==2 ~ "B" ,
results.condition=='baseline' & results.format=="1:3" & round==3 ~ "C"
))
Set-up for factors for viability questions:
data <- rename(data, "repeatTeam" = results.viabilityCheck.15)
## Remove observations where viability survey wasn't on (remove this line if we want to keep observations with viability off):
data <- na.omit(data)
## Factor for visualizations:
levels <- c("Strongly Disagree", "Disagree", "Neutral","Agree", "Strongly Agree")
clean <- data %>%
mutate_at(.vars = vars(contains("results.viabilityCheck")), funs(factor(., levels = levels)))
## Create a new dataframe that converts factors to numeric for statistical analyses:
stats <- clean %>% mutate_if(is.factor, as.numeric)
for (i in 1:nrow(stats)) {
stats$sum[i] <- sum(stats[i,1:14])
}
stats$median <- median(stats$sum)
stats$mean <- mean(stats$sum)
## Revalue repeat team: keep plyr b/c some weird R stuff requires library to be called directly (recode values to )
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Yes"="0", "No"="1"))
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Keep this team"="0", "Do not keep this team"="1"))
## Convert to compatible classes for team grouping:
stats$repeatTeam <- as.numeric(stats$repeatTeam)
stats$results.condition <- unlist(stats$results.condition)
stats$results.format <- as.character(stats$results.format)
stats$room <- unlist(stats$room)
## Dplyr to group teams and summarise variables for each group: group_by to find teams and summarise to compact individual results into group level results (i.e. one row of variable results per team)
groupedProportion <- stats %>%
group_by(room, batch, round, condition, results.condition, results.format) %>% ## to-do: add group ID in storage db.
summarise(n=n(), mean=mean(sum), median=median(sum),prop=sum(repeatTeam)/n, groupID=runif(1,0,2)) %>%
## Filter out all teams with n=1 (i.e. a person in a one person team)
filter(n==2)
## Individual proportion:
individualProportion <- stats %>% group_by(round, batch, room) %>%
mutate(sum=sum, mean=mean(sum), median=median(sum), n=n(),prop=sum(repeatTeam)/n) %>%
filter(n>1)
## Table showing how many teams we've run in each condition combination:
print(table(groupedProportion$condition, groupedProportion$results.condition))
baseline control treatment
A 26 10 25
Ap 0 10 25
B 20 14 22
C 29 0 0
Probability of fracture across teams and condition combinations:
left_join(baselineFracture1, baselineFracture2, by=NULL, drop=TRUE)
Joining, by = c("room", "batch", "round", "condition", "results.condition", "results.format", "n", "mean", "median", "prop", "groupID", "fracture")
Section #1: Does fracture have continuity with prior measures?
1A: Report the % of correct guesses on the manipulation check:
## Treatment manipulation:
treatmentManipulation <- cleanManipulation %>% group_by(id, results.condition, manipulationAnswers, manipulationAnswerKey) %>% filter(results.condition=="treatment") %>%
summarise(n=n())
## If user manipulation answers == manipulation answer key then add 1
treatmentManipulation$correctAnswers <- sum(ifelse(treatmentManipulation$manipulationAnswers==treatmentManipulation$manipulationAnswerKey,1,0))
## Calculate percent of correct manipulation answers for treatment:
treatmentManipulation <- treatmentManipulation %>% mutate(percentCorrect = (correctAnswers/(nrow(treatmentManipulation))))
## Control manipulation:
controlManipulation <- cleanManipulation %>% group_by(id, results.condition, manipulationAnswers, manipulationAnswerKey) %>% filter(results.condition=="control") %>%
summarise(n=n())
## If user manipulation answers == manipulation answer key then add 1
controlManipulation$correctAnswers <- sum(ifelse(controlManipulation$manipulationAnswers==controlManipulation$manipulationAnswerKey,1,0))
## Calculate percent of correct manipulation answers for control:
controlManipulation <- controlManipulation %>% mutate(percentCorrect = (correctAnswers/(nrow(controlManipulation))))
## Proportion test comparing treatment manipulation percent correct with chance:
1B: Proportion test comparing treatment manipulation percent correct with chance:
## ⅓ ~ 33% = chance, ~43 = treatment (FILL-IN EACH TIME YOU RUN WITH NEW DATA!)
propManipulation <- prop.test(x = c(33, 43), n = c(100, 100))
print(propManipulation)
2-sample test for equality of proportions with continuity correction
data: c(33, 43) out of c(100, 100)
X-squared = 1.719, df = 1, p-value = 0.1898
alternative hypothesis: two.sided
95 percent confidence interval:
-0.24382407 0.04382407
sample estimates:
prop 1 prop 2
0.33 0.43
1C: Logistic regression predicting binary fracture outcome from viability scales:
## Split data into 60% training and 40% testing data sets to test how well the model performs
set.seed(123)
groupedProportionFracture$fracture <- as.numeric(groupedProportionFracture$fracture)
sample <- sample(c(TRUE, FALSE), nrow(groupedProportionFracture), replace = T, prob = c(0.6,0.4))
train <- groupedProportionFracture[sample, ]
test <- groupedProportionFracture[!sample, ]
## Simple logistic regression: we will fit a logistic regression model in order to predict
## the probability of fracture based on a team's average viability sum:
model1 <- glm(fracture ~ mean, family = "binomial", data = train)
summary(model1)
Call:
glm(formula = fracture ~ mean, family = "binomial", data = train)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.94811 -0.46471 0.04798 0.38542 2.43161
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 13.79411 2.58357 5.339 9.34e-08 ***
mean -0.26503 0.04908 -5.400 6.68e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 152.165 on 109 degrees of freedom
Residual deviance: 71.765 on 108 degrees of freedom
AIC: 75.765
Number of Fisher Scoring iterations: 6
## To assess the linear regression deviance, look at deviance in summary output, if
## deviance == sum of sqaures in linear regression, null deviance == difference between
## a model with only the intercept ("no mean predictors") and the a saturated model
## a model with a theoretically perfect fit. Model deviance (residual deviance) should be lower
## small values == better fit.
tidy(model1)
## Coefficient estimtes from log regression characterize relationship between the predictor and
## response variable on a log-odds scale, so binary increase from no fracture - fracture can be interpreted as associated with a decrease in mean viability sum.
## More coefficient output: measure the confidence intervals and accuracy of the coefficent:
confint(model1)
Waiting for profiling to be done...
2.5 % 97.5 %
(Intercept) 9.3617399 19.6211689
mean -0.3757527 -0.1807974
## Making predictions:
## What is the probability of fracture given the following team mean viability scores: for example purposes: 40 and 65:
predict(model1, data.frame(mean = c(50, 65)), type = "response")
1 2
0.63238720 0.03127928
## From the output, we can see that the probability of fracture decreases by ~40% when mean viability sum increases from 40 to 65.
## Model evaluation & diagnostics:
## How well does the model fit the data? And how accurate are the predictions on an out-of-sample data set?
## Residul assessment:
model1_data <- augment(model1) %>%
mutate(index = 1:n())
ggplot(model1_data, aes(index, .std.resid, color = mean)) +
geom_point(alpha = .5) +
geom_ref_line(h = 3)

## Validation of predicted values:
## How well does the model perform when predicting the target variable on out-of-sample observations?
test.predicted.m1 <- predict(model1, newdata = test, type = "response")
## Classification performance for each model on the test data. Output gives us a list of true / false positives:
list(
model1 = table(test$mean, test.predicted.m1 > 0.5) %>% prop.table() %>% round(3))
$model1
FALSE TRUE
32 0.000 0.014
32.5 0.000 0.014
36 0.000 0.028
36.5 0.000 0.014
37 0.000 0.014
41.5 0.000 0.028
44 0.000 0.014
45 0.000 0.014
46.5 0.000 0.028
47 0.000 0.014
48.5 0.000 0.042
49 0.000 0.028
49.5 0.000 0.014
50 0.000 0.028
50.5 0.000 0.014
52 0.000 0.028
52.5 0.014 0.000
53 0.028 0.000
54 0.028 0.000
54.5 0.014 0.000
55.5 0.028 0.000
56 0.099 0.000
56.5 0.014 0.000
57 0.028 0.000
58 0.028 0.000
58.5 0.042 0.000
59 0.014 0.000
59.5 0.014 0.000
60 0.014 0.000
60.5 0.014 0.000
61 0.014 0.000
61.5 0.028 0.000
62 0.028 0.000
62.5 0.014 0.000
63 0.056 0.000
64 0.014 0.000
65 0.014 0.000
66 0.014 0.000
66.5 0.014 0.000
69 0.014 0.000
70 0.070 0.000
table(test$mean, test.predicted.m1 > 0.5)
FALSE TRUE
32 0 1
32.5 0 1
36 0 2
36.5 0 1
37 0 1
41.5 0 2
44 0 1
45 0 1
46.5 0 2
47 0 1
48.5 0 3
49 0 2
49.5 0 1
50 0 2
50.5 0 1
52 0 2
52.5 1 0
53 2 0
54 2 0
54.5 1 0
55.5 2 0
56 7 0
56.5 1 0
57 2 0
58 2 0
58.5 3 0
59 1 0
59.5 1 0
60 1 0
60.5 1 0
61 1 0
61.5 2 0
62 2 0
62.5 1 0
63 4 0
64 1 0
65 1 0
66 1 0
66.5 1 0
69 1 0
70 5 0
1D: Graph of fracture/no fracture vs. mean/stdev viability scale
## Overall:
g <- ggplot(groupedProportionFracture, aes(factor(fracture), mean))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Team fracture value vs. mean viability score: fracture >=0.50 across all conditions (n=2)",
x="",
y="Numeric sum of viability measures questions (range: 7-70)")

## By condition + format:
g <- ggplot(groupedProportionFracture, aes(factor(fracture), mean))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Team fracture value vs. mean viability score: fracture >=0.50 (n=2)",
x="",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.condition)

ggplot(data=groupedProportionFracture, aes(fracture, mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(main="Scatterplot of fracture value vs. mean for team viability sums across all conditions (n=2)") + facet_grid(condition ~ results.condition)

ggplot(data=groupedProportionFracture, aes(fracture, mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(main="Scatterplot of fracture value vs. mean for team viability sums (n=2)") + facet_grid(condition ~ results.condition)

Section #2: How often does fracture occur?
2A: P(binary fracture) histogram of fracture proportion (by team)
## First make sure you've made ABC condition
ggplot(data=groupedProportion, aes(groupedProportion$prop)) +
geom_histogram(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Frequency of team fracture proportions by condition and pattern sequence",
x="team fracture proportion", y="Count") + facet_grid(results.condition ~ .)


library(MASS)
Attaching package: ‘MASS’
The following object is masked from ‘package:dplyr’:
select
The following object is masked from ‘package:plotly’:
select
## Test if whether fracture smoking habit is independent of condition at .05 significance level:
chi = table(groupedProportionFracture$fracture, groupedProportionFracture$results.condition)
chi
baseline control treatment
0 41 18 38
1 34 16 34
print(chisq.test(chi))
Pearson's Chi-squared test
data: chi
X-squared = 0.059809, df = 2, p-value = 0.9705
2B: What’s the overall % of fracturing the second time? (by condition)
## Filtering second time only:
groupedProportionFracture$fracture <- as.numeric(groupedProportionFracture$fracture)
## TO-DO: review below code, worried it's incorrect:
groupedProportionFractureSecond <- groupedProportionFracture %>% group_by(results.condition) %>%
filter(condition=="Ap") %>%
mutate(overallPercent = sum(as.numeric(fracture))) %>%
summarise(n=n(), overallPercent=unique(overallPercent)/n)
print(groupedProportionFractureSecond)
## For baseline theoretical distribution: (to-do: look over this, worried also that it's wrong)
groupedProportionFractureSecondBase <- groupedProportionFractureBaseline %>%
filter(round=="3") %>%
summarise(n=n(), overallPercent=sum(as.numeric(fracture))/n)
print(mean(groupedProportionFractureSecondBase$overallPercent))
[1] 0.4930556
## Set-up separate groups for proportion tests to answer: does unmasked fracture more/less than masked
## and more/less than new pairs?
## Control:
## Proportion tests for each (TO-DO, figure out argument stuff: this doesn't seem like the right test to run for the question we're asking?) also, fill-this in every time you get new data:
## Is the proportion of fracture in the second round significantly different in the two conditions (i.e. treatment + baseline)
treatmentvsBaselineChange <- c(48, 49)
propFractureChangeTreatmentvsBase <- prop.test(x = c(treatmentvsBaselineChange), n = c(100, 100))
print(propFractureChangeTreatmentvsBase)
2-sample test for equality of proportions with continuity correction
data: c(treatmentvsBaselineChange) out of c(100, 100)
X-squared = 0, df = 1, p-value = 1
alternative hypothesis: two.sided
95 percent confidence interval:
-0.1585211 0.1385211
sample estimates:
prop 1 prop 2
0.48 0.49
## Is the proportion of fracture in the second round significantly different in the two conditions (i.e. control + baseline)
controlvsBaselineChange <- c(40, 49)
propFractureChangeControlvsBase <- prop.test(x = c(controlvsBaselineChange), n = c(100, 100))
print(propFractureChangeControlvsBase)
2-sample test for equality of proportions with continuity correction
data: c(controlvsBaselineChange) out of c(100, 100)
X-squared = 1.2957, df = 1, p-value = 0.255
alternative hypothesis: two.sided
95 percent confidence interval:
-0.23718348 0.05718348
sample estimates:
prop 1 prop 2
0.40 0.49
Section 3: How consistent is fracture?
3A: calculating the conditional probabilities of fracture for each condition:
controlFracture12 <- sum(ifelse(controlFracture1$fracture=="1" & controlFracture2$fracture=="1",1,0))/nrow(controlFracture)
# of groups who fractured only 1
controlFractureOnly1 <- sum(ifelse(controlFracture1$fracture=="1" & controlFracture2$fracture=="0",1,0))/nrow(controlFracture)
# of groups who fractured only 2
controlFractureOnly2 <- sum(ifelse(controlFracture1$fracture=="0" & controlFracture2$fracture=="1",1,0))/nrow(controlFracture)
# of groups who fractured never
controlFractureNever <- sum(ifelse(controlFracture1$fracture=="0" & controlFracture2$fracture=="0",1,0))/nrow(controlFracture)
conditionalProbControl <- matrix(c(controlFracture12, controlFractureOnly1, controlFractureOnly2, controlFractureNever),ncol=2,byrow=TRUE)
colnames(conditionalProbControl) <- c("Ap frac","Ap no frac")
rownames(conditionalProbTreatment) <- c("A frac","A no frac")
conditionalProbControl <- as.table(conditionalProbControl)
conditionalProbControl
Ap frac Ap no frac
A 0.3 0.0
B 0.1 0.6
3B: Now investigating the big result: switch %: what’s the % of pairs flipping their decisions?
controlFractureAbsSum <- sum(controlFracture$absFracture)
print(controlFractureAbsSum)
[1] 1
LS0tCnRpdGxlOiAiQXNwbG9kZSB0ZXN0IG91dGxpbmUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIFNldC11cCBwYWNrYWdlcyAvLyBsaWJyYXJpZXMgYW5kIHByZXBhcmUgZm9yIGRhdGEgaW1wb3J0OiAKYGBge3J9CiMjIFVuY29tbWVudCBpbnN0YWxsLnBhY2thZ2VzIGFuZCBydW4gb3V0c2lkZSBvZiBub3RlYm9vayBlbnZpcm9ubWVudDogCiMjIGluc3RhbGwucGFja2FnZXMoYygicHN5Y2giICwieHRhYmxlIiwgInRpZHl2ZXJzZSIsICJqc29ubGl0ZSIsICJsaWtlcnQiLCAiZ2dwbG90MiIsICJwbG90eSIsICJtb3NhaWMiLCAibW9kZWxyIiwgImJyb29tIikpCgpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGxpa2VydCkKbGlicmFyeShqc29ubGl0ZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShtb2RlbHIpCmxpYnJhcnkoYnJvb20pCnNvdXJjZSgiaHR0cDovL3Bjd3d3Lmxpdi5hYy51ay9+d2lsbGlhbS9SL2Nyb3NzdGFiLnIiKQp0aGVtZV9zZXQodGhlbWVfY2xhc3NpYygpKQpgYGAKCiMjIFNldC11cCBkaXJlY3RvcmllcywgaW1wb3J0IGFuZCBjbGVhbiBkYXRhOiAKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIi9Vc2Vycy9hbGxpZWJsYWlzaW5nL2Rlc2t0b3AvYmFuZy9SIikgCmdldHdkKCkKZGF0YVBhdGggPSAiLi4vLmRhdGEiCiMjIERlZmluZSBmdW5jdGlvbiB0byBleHRyYWN0IHN1cnZleSByZXN1bHRzOiAKZXh0cmFjdFN1cnZleSA9IGZ1bmN0aW9uKGZyYW1lLHN1cnZleSkgewogIHJvdW5kcyA9IHNlcSgxLGxlbmd0aChmcmFtZSRyZXN1bHRzLmZvcm1hdFtbMV1dKSkKICByb3VuZFJlc3BvbnNlcyA9IGxhcHBseShyb3VuZHMsIGZ1bmN0aW9uKHJvdW5kKSB7CiAgICBnZXRDb2wgPSBwYXN0ZSgicmVzdWx0cy4iLHN1cnZleSwiLiIscm91bmQsIHNlcD0iIikKICAgIHN1cnZleUNvbHMgPSBGaWx0ZXIoZnVuY3Rpb24oeCkgZ3JlcGwoZ2V0Q29sLHgpLG5hbWVzKGZyYW1lKSkKICAgIG5ld0NvbHMgPSBsYXBwbHkoc3VydmV5Q29scywgZnVuY3Rpb24oeCkgZ3N1YihnZXRDb2wscGFzdGUoInJlc3VsdHMuIixzdXJ2ZXksIHNlcD0iIikseCkgKQogICAgc3VydmV5RnJhbWUgPSBmcmFtZVssc3VydmV5Q29sc10KICAgIGlmIChpcy5udWxsKG5ld0NvbHMpKSB7cmV0dXJuKCJObyBuZXdDb2xzIil9CiAgICBuYW1lcyhzdXJ2ZXlGcmFtZSkgPSBuZXdDb2xzCiAgICBzdXJ2ZXlGcmFtZSRpZCA9IGZyYW1lJGlkCiAgICBzdXJ2ZXlGcmFtZSRyb3VuZCA9IHJvdW5kCiAgICBzdXJ2ZXlGcmFtZSRiYXRjaCA9IGZyYW1lJGJhdGNoCiAgICBzdXJ2ZXlGcmFtZSRyb29tcyA9IGZyYW1lJHJvb21zCiAgICBzdXJ2ZXlGcmFtZSRtYW5pcHVsYXRpb24gPSBmcmFtZSRyZXN1bHRzLm1hbmlwdWxhdGlvbkNoZWNrCiAgICBzdXJ2ZXlGcmFtZSRibGFja2xpc3QgPSBmcmFtZSRyZXN1bHRzLmJsYWNrbGlzdENoZWNrCiAgICByZXR1cm4oc3VydmV5RnJhbWUpCiAgfSkKICByZXR1cm4oUmVkdWNlKHJiaW5kLCByb3VuZFJlc3BvbnNlcykpCn0KI0ZpbmQgZGlyZWN0b3J5IGZvciBpbXBvcnQgKGJlIHN1cmUgdG8gdmVyaWZ5IHRoYXQgYmF0Y2ggI3MgYWxpZ24gZnJvbSBiYW5nRGF0YSBpbXBvcnQgYW5kIGltcG9ydHMgYmVsb3cpOiAKYmF0Y2hlcyA9IGRpcihkYXRhUGF0aCwgcGF0dGVybiA9ICJeWzAtOV0rJCIgKQpjb21wbGV0ZUJhdGNoZXMgPSBGaWx0ZXIoZnVuY3Rpb24oYmF0Y2gpIHsgCiAgaWYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJiYXRjaC5qc29uIikgJiYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJ1c2Vycy5qc29uIikpICkgewogICAgYmF0Y2hEYXRhID0gcmVhZF9qc29uKHBhc3RlKGRhdGFQYXRoLGJhdGNoLCJiYXRjaC5qc29uIixzZXA9Ii8iKSwgc2ltcGxpZnlWZWN0b3IgPSBUUlVFKQogICAgcmV0dXJuKGFueShiYXRjaERhdGEkYmF0Y2hDb21wbGV0ZSA9PSBUUlVFKSkKICB9IAogIHJldHVybihGQUxTRSkKfSwgYmF0Y2hlcykKdXNlckZpbGVzID0gbGFwcGx5KGNvbXBsZXRlQmF0Y2hlcywgZnVuY3Rpb24oYmF0Y2gpIHsKICB1c2VyRmlsZSA9IHJlYWRfanNvbihwYXN0ZShkYXRhUGF0aCxiYXRjaCwidXNlcnMuanNvbiIsc2VwPSIvIiksIHNpbXBsaWZ5VmVjdG9yPVRSVUUpCiAgcmV0dXJuKGZsYXR0ZW4odXNlckZpbGUsIHJlY3Vyc2l2ZSA9IFRSVUUpKQp9KQoKIyMgUmV0cm9hY3RpdmVseSBmaW5kIHJvb21zIGZyb20gY2hhdCBkYXRhOiAKb3ZlcmxhcHBpbmdGaWxlcyA9IFJlZHVjZShmdW5jdGlvbih4LHkpIG1lcmdlKHgsIHksIGFsbD1UUlVFKSwgdXNlckZpbGVzKQpyb3VuZHNXaXRoUm9vbXMgPSBhcHBseShvdmVybGFwcGluZ0ZpbGVzLDEsZnVuY3Rpb24oeCkgewogIHJvb21zRm9ySW5kaXZpZHVhbCA9IGxhcHBseShzZXEoMSwzKSxmdW5jdGlvbih5KSB7CiAgICB4JHJvb20gPSB4JHJvb21zW3ldCiAgICB4JHJvdW5kID0geQogICAgcmV0dXJuKHgpCiAgfSkKICByZXR1cm4oUmVkdWNlKHJiaW5kLCByb29tc0ZvckluZGl2aWR1YWwpKQp9KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtb3NhaWMpCgojIyBUbyBmaWx0ZXIgdGhlIHJpZ2h0IGJhdGNoIG51bWJlcnMsIGFkZCB0aGUgZmlyc3QgYmF0Y2ggbnVtYmVyIGZvciBvdXIgcnVucyAoaS5lLiBiYXRjaCA+PSAiZmlyc3QgYmF0Y2ggIyIpICAKIyMgb3ZlcmxhcHBpbmdGaWxlcyA8LSBvdmVybGFwcGluZ0ZpbGVzICU+JSBmaWx0ZXIoYmF0Y2g9PSIxNTM2MTMyMjMzMDc0IikKCmBgYAoKIyMgTW9yZSBjbGVhbmluZyBiZWZvcmUgdmlzdWFsaXphdGlvbnM6IApgYGB7cn0KIyMgRm9yIHdoZW4gd2Ugc3RhcnQgaW5wdXR0aW5nIG5ldyBiYXRjaGVzIG9ubHk6IAojIG92ZXJsYXBwaW5nRmlsZXMgPC0gb3ZlcmxhcHBpbmdGaWxlcyAlPiUgZmlsdGVyKGJhdGNoPj0iMTUzNjI3NjkwNDU0NyIpIAojIHFGaWZ0ZWVuIDwtIGFzLmRhdGEuZnJhbWUoZXh0cmFjdFN1cnZleShvdmVybGFwcGluZ0ZpbGVzLCAncUZpZnRlZW5DaGVjaycpKQojIHFTaXh0ZWVuIDwtIGFzLmRhdGEuZnJhbWUoZXh0cmFjdFN1cnZleShvdmVybGFwcGluZ0ZpbGVzLCAncVNpeHRlZW5DaGVjaycpKQojIHZpYWJpbGl0eVN1cnZleSA8LSBhcy5kYXRhLmZyYW1lKGV4dHJhY3RTdXJ2ZXkob3ZlcmxhcHBpbmdGaWxlcywgJ3ZpYWJpbGl0eUNoZWNrJykpICAKIyBxRmlmdGVlbiA8LSBxRmlmdGVlbiAlPiUgc2VsZWN0KGlkLCByZXN1bHRzLnFGaWZ0ZWVuQ2hlY2spCiMgcVNpeHRlZW4gPC0gcVNpeHRlZW4gJT4lIHNlbGVjdChpZCwgcmVzdWx0cy5xU2l4dGVlbkNoZWNrKSAKIyBxRmlmdGVlbiRpZCA8LSAgdW5saXN0KHFGaWZ0ZWVuJGlkKQojIHFTaXh0ZWVuJGlkIDwtICB1bmxpc3QocVNpeHRlZW4kaWQpCiMgcG9zdFN1cnZleVFzIDwtIGNiaW5kKHFGaWZ0ZWVuLCBxU2l4dGVlbikgCiMgZnJhbWUgPC0gY2JpbmQodmlhYmlsaXR5U3VydmV5LCBwb3N0U3VydmV5UXMpICAKIyBmcmFtZSA8LSBmcmFtZVssICFkdXBsaWNhdGVkKGNvbG5hbWVzKGZyYW1lKSldCgpmcmFtZSA8LSBleHRyYWN0U3VydmV5KG92ZXJsYXBwaW5nRmlsZXMsICd2aWFiaWxpdHlDaGVjaycpCiMjIFJlZHVjZSB0byB2ZXJ0aWNhbGx5IGNvbWJpbmUgcm93cyBpbiByb3VuZHdpdGhSb29tcyBsaXN0OiAgCmZpbmFsUm91bmRzID0gYXMuZGF0YS5mcmFtZShSZWR1Y2UocmJpbmQscm91bmRzV2l0aFJvb21zKSkKIyMgU3Vic2V0IGluY29tcGxldGUgY2FzZXMgZnJvbSB2aWFiaWxpdHkgc3VydmV5IGRhdGFmcmFtZSwgdXNlIG1hbmlwdWxhdGlvbiBjaGVjayBiL2MgcmVxdWlyZWQgZm9yIGNvbXBsZXRlIG9ic2VydmF0aW9uOiAKZGF0YSA8LSBmcmFtZVtmcmFtZSRtYW5pcHVsYXRpb24hPSIiLF0KIyMgUmVuYW1lIHJvb20gdG8gcm9vbXMgc28gdGhhdCBib3RoIGFyZSByZXRhaW5lZCBpbiBmdXR1cmUgbWVyZ2U6IApkYXRhIDwtIHJlbmFtZShkYXRhLCByb29tcyA9ICJyb29tcyIpCiMjIFN1YnNldCBpbmNvbXBsZXRlIGNhc2VzIGZvciBmaW5hbCByb3VuZHMgZGF0YWZyYW1lOiAKZGF0YTIgPC0gZmluYWxSb3VuZHNbZmluYWxSb3VuZHMkcmVzdWx0cy5tYW5pcHVsYXRpb25DaGVjayE9IiIsIF0KIyMgU2VsZWN0IG9ubHkgdmFyaWFibGVzIG9mIGludGVyZXN0IGZyb20gZmluYWwgcm91bmRzOiAKZGF0YTIgPSBkYXRhMiAlPiUgc2VsZWN0KGlkLCBiYXRjaCwgcm9vbSwgYm9udXMsIG5hbWUsIGZyaWVuZHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgZnJpZW5kc19oaXN0b3J5LCByZXN1bHRzLmNvbmRpdGlvbiwgcmVzdWx0cy5mb3JtYXQsCiAgICAgICAgICAgICAgICAgIHJlc3VsdHMubWFuaXB1bGF0aW9uLHJlc3VsdHMubWFuaXB1bGF0aW9uQ2hlY2sscmVzdWx0cy5ibGFja2xpc3RDaGVjaywgcm91bmQpCiMjIENvbnZlcnQgdG8gY29tcGF0aWJsZSBkYXRhIHR5cGVzIGJlZm9yZSBtZXJnZSAoKip0aGlzIHNob3VsZCBiZSBzaW1wbGlmaWVkKiopCmRhdGEyJGJhdGNoIDwtIHVubGlzdChkYXRhMiRiYXRjaCkKZGF0YTIkcm91bmQgPC0gdW5saXN0KGRhdGEyJHJvdW5kKQpkYXRhMiRpZCA8LSB1bmxpc3QoZGF0YTIkaWQpIApkYXRhJGJhdGNoIDwtIHVubGlzdChkYXRhJGJhdGNoKQoKIyMgQmVmb3JlIG1lcmdlLCBkYXRhIGFuZCBkYXRhMiBzaG91bGQgaGF2ZSB0aGUgc2FtZSAjIG9mIG9ic2VydmF0aW9ucwojIyBNZXJnZSBjb2x1bW5zIGJ5IGlkLCByb3VuZCBhbmQgYmF0Y2ggI3M6IApkYXRhIDwtIGxlZnRfam9pbihkYXRhLCBkYXRhMiwgYnk9TlVMTCkKIyMgU3Vic2V0IG9ubHkgb2JzZXJ2YXRpb25zIHdpdGggYmF0Y2ggI3MgaW4gY29tcGxldGUgYmF0Y2hlcyAKYWxsQ29uZGl0aW9ucyA8LSBkYXRhW2RhdGEkYmF0Y2ggJWluJSBjb21wbGV0ZUJhdGNoZXMsIF0KYGBgCiMjIENvbmRpdGlvbmFsbHkgYXNzaWduIGNvbmRpdGlvbnMgYmFzZWQgb24gdHJlYXRtZW50IGFuZCByZXN1bHRzIGNvbHVtbjogCmBgYHtyfQojIyBNZXNzeSwgYnV0IHJvYnVzdD8gVmVyaWZ5LCB2ZXJpZnksIHZlcmlmeSBwZW9wbGU6ICAgCmRhdGEgPC0gZGF0YSAlPiUgbXV0YXRlKAogIGNvbmRpdGlvbiA9IGNhc2Vfd2hlbigKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MSB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTIgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTEgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0yIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTMgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0xIH4gIkIiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MiB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTMgfiAiQXAiICwKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTEgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MiB+ICJCIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0xIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTIgfiAiQXAiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiICYgcm91bmQ9PTMgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MSB+ICJCIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0yIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTMgfiAiQXAiICwKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nYmFzZWxpbmUnICYgcmVzdWx0cy5mb3JtYXQ9PSIxOjMiICYgcm91bmQ9PTEgfiAiQSIgLAogICAgcmVzdWx0cy5jb25kaXRpb249PSdiYXNlbGluZScgJiByZXN1bHRzLmZvcm1hdD09IjE6MyIgJiByb3VuZD09MiB+ICJCIiAsCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2Jhc2VsaW5lJyAmIHJlc3VsdHMuZm9ybWF0PT0iMTozIiAmIHJvdW5kPT0zIH4gIkMiIAogICkpIAoKYGBgCgojIyBTZXQtdXAgZm9yIGZhY3RvcnMgZm9yIHZpYWJpbGl0eSBxdWVzdGlvbnM6IApgYGB7cn0KZGF0YSA8LSByZW5hbWUoZGF0YSwgInJlcGVhdFRlYW0iID0gcmVzdWx0cy52aWFiaWxpdHlDaGVjay4xNSkKIyMgUmVtb3ZlIG9ic2VydmF0aW9ucyB3aGVyZSB2aWFiaWxpdHkgc3VydmV5IHdhc24ndCBvbiAocmVtb3ZlIHRoaXMgbGluZSBpZiB3ZSB3YW50IHRvIGtlZXAgb2JzZXJ2YXRpb25zIHdpdGggdmlhYmlsaXR5IG9mZik6IApkYXRhIDwtIG5hLm9taXQoZGF0YSkKIyMgRmFjdG9yIGZvciB2aXN1YWxpemF0aW9uczogCmxldmVscyA8LSBjKCJTdHJvbmdseSBEaXNhZ3JlZSIsICJEaXNhZ3JlZSIsICJOZXV0cmFsIiwiQWdyZWUiLCAiU3Ryb25nbHkgQWdyZWUiKSAKY2xlYW4gPC0gZGF0YSAlPiUgCiAgbXV0YXRlX2F0KC52YXJzID0gdmFycyhjb250YWlucygicmVzdWx0cy52aWFiaWxpdHlDaGVjayIpKSwgZnVucyhmYWN0b3IoLiwgbGV2ZWxzID0gbGV2ZWxzKSkpIAojIyBDcmVhdGUgYSBuZXcgZGF0YWZyYW1lIHRoYXQgY29udmVydHMgZmFjdG9ycyB0byBudW1lcmljIGZvciBzdGF0aXN0aWNhbCBhbmFseXNlczoKc3RhdHMgPC0gY2xlYW4gJT4lIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLm51bWVyaWMpCmZvciAoaSBpbiAxOm5yb3coc3RhdHMpKSB7CiAgc3RhdHMkc3VtW2ldIDwtIHN1bShzdGF0c1tpLDE6MTRdKSAgICAgICAgICAgICAgICAgICAgICAgICAgCn0gCnN0YXRzJG1lZGlhbiA8LSBtZWRpYW4oc3RhdHMkc3VtKQpzdGF0cyRtZWFuIDwtIG1lYW4oc3RhdHMkc3VtKQojIyBSZXZhbHVlIHJlcGVhdCB0ZWFtOiBrZWVwIHBseXIgYi9jIHNvbWUgd2VpcmQgUiBzdHVmZiByZXF1aXJlcyBsaWJyYXJ5IHRvIGJlIGNhbGxlZCBkaXJlY3RseSAocmVjb2RlIHZhbHVlcyB0byApCnN0YXRzJHJlcGVhdFRlYW0gPC0gcGx5cjo6cmV2YWx1ZShzdGF0cyRyZXBlYXRUZWFtLCBjKCJZZXMiPSIwIiwgIk5vIj0iMSIpKQpzdGF0cyRyZXBlYXRUZWFtIDwtIHBseXI6OnJldmFsdWUoc3RhdHMkcmVwZWF0VGVhbSwgYygiS2VlcCB0aGlzIHRlYW0iPSIwIiwgIkRvIG5vdCBrZWVwIHRoaXMgdGVhbSI9IjEiKSkKIyMgQ29udmVydCB0byBjb21wYXRpYmxlIGNsYXNzZXMgZm9yIHRlYW0gZ3JvdXBpbmc6IApzdGF0cyRyZXBlYXRUZWFtIDwtIGFzLm51bWVyaWMoc3RhdHMkcmVwZWF0VGVhbSkKc3RhdHMkcmVzdWx0cy5jb25kaXRpb24gPC0gdW5saXN0KHN0YXRzJHJlc3VsdHMuY29uZGl0aW9uKQpzdGF0cyRyZXN1bHRzLmZvcm1hdCA8LSBhcy5jaGFyYWN0ZXIoc3RhdHMkcmVzdWx0cy5mb3JtYXQpCnN0YXRzJHJvb20gPC0gdW5saXN0KHN0YXRzJHJvb20pCiMjIERwbHlyIHRvIGdyb3VwIHRlYW1zIGFuZCBzdW1tYXJpc2UgdmFyaWFibGVzIGZvciBlYWNoIGdyb3VwOiBncm91cF9ieSB0byBmaW5kIHRlYW1zIGFuZCBzdW1tYXJpc2UgdG8gY29tcGFjdCBpbmRpdmlkdWFsIHJlc3VsdHMgaW50byBncm91cCBsZXZlbCByZXN1bHRzIChpLmUuIG9uZSByb3cgb2YgdmFyaWFibGUgcmVzdWx0cyBwZXIgdGVhbSkKZ3JvdXBlZFByb3BvcnRpb24gPC0gc3RhdHMgJT4lCiAgZ3JvdXBfYnkocm9vbSwgYmF0Y2gsIHJvdW5kLCBjb25kaXRpb24sIHJlc3VsdHMuY29uZGl0aW9uLCByZXN1bHRzLmZvcm1hdCkgJT4lICAjIyB0by1kbzogYWRkIGdyb3VwIElEIGluIHN0b3JhZ2UgZGIuIAogIHN1bW1hcmlzZShuPW4oKSwgbWVhbj1tZWFuKHN1bSksIG1lZGlhbj1tZWRpYW4oc3VtKSxwcm9wPXN1bShyZXBlYXRUZWFtKS9uLCBncm91cElEPXJ1bmlmKDEsMCwyKSkgJT4lIAojIyBGaWx0ZXIgb3V0IGFsbCB0ZWFtcyB3aXRoIG49MSAoaS5lLiBhIHBlcnNvbiBpbiBhIG9uZSBwZXJzb24gdGVhbSkgCiAgZmlsdGVyKG49PTIpCgojIyBJbmRpdmlkdWFsIHByb3BvcnRpb246IAppbmRpdmlkdWFsUHJvcG9ydGlvbiA8LSBzdGF0cyAlPiUgZ3JvdXBfYnkocm91bmQsIGJhdGNoLCByb29tKSAlPiUgCiAgbXV0YXRlKHN1bT1zdW0sIG1lYW49bWVhbihzdW0pLCBtZWRpYW49bWVkaWFuKHN1bSksIG49bigpLHByb3A9c3VtKHJlcGVhdFRlYW0pL24pICU+JSAKICBmaWx0ZXIobj4xKQoKIyMgVGFibGUgc2hvd2luZyBob3cgbWFueSB0ZWFtcyB3ZSd2ZSBydW4gaW4gZWFjaCBjb25kaXRpb24gY29tYmluYXRpb246ICAKcHJpbnQodGFibGUoZ3JvdXBlZFByb3BvcnRpb24kY29uZGl0aW9uLCBncm91cGVkUHJvcG9ydGlvbiRyZXN1bHRzLmNvbmRpdGlvbikpIApgYGAKCiMjIFByb2JhYmlsaXR5IG9mIGZyYWN0dXJlIGFjcm9zcyB0ZWFtcyBhbmQgY29uZGl0aW9uIGNvbWJpbmF0aW9uczogCmBgYHtyfQojIyBEZWZpbmUgYW5kIGluaXRpYWxpemUgY3V0LW9mZiBwb2ludCBmb3IgZnJhY3R1cmU6IApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlIDwtIGdyb3VwZWRQcm9wb3J0aW9uICU+JQogIGdyb3VwX2J5KHJlc3VsdHMuY29uZGl0aW9uLCBjb25kaXRpb24pICU+JSAKICBtdXRhdGUoZnJhY3R1cmUgPSBjYXNlX3doZW4gKHByb3A8LjUwIH4gIjAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wPj0uNTB+ICIxIikpIAoKIyMgQmFzZWxpbmU6ICh3ZSBwcm9iYWJseSB3b24ndCBuZWVkIHRoaXMgc2luY2Ugd2UgYXJlIGFydGlmaWNpYWxseSBtYWtpbmcgYmFzZWxpbmUgY29uZGl0aW9ucykKIyBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlQmFzZWxpbmUgPC0gCiMgICBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlICU+JSAKIyBmaWx0ZXIocmVzdWx0cy5jb25kaXRpb249PSJiYXNlbGluZSIpICU+JSAKIyAgIGZpbHRlcihpZCAlaW4lIGNvbmRpdGlvbj09IkEiICYgY29uZGl0aW9uPT0iQyIpCiMgYmFzZWxpbmVGcmFjdHVyZTEgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUJhc2VsaW5lICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIpCiMgYmFzZWxpbmVGcmFjdHVyZTIgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUJhc2VsaW5lICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQyIpCgojIFRPLURPOiBjaGVjayBpZiB0aGlzIGlzIHJpZ2h0LS1zZWVtcyBvZmYgKHdoeSBpcyBiYXNlbGluZSBvZmY/KQoKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUJhc2VsaW5lIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUgJT4lIGZpbHRlcihyZXN1bHRzLmZvcm1hdD09ImMoMSwgMSwgMikiIHwgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIikgJT4lIGZpbHRlcihyb3VuZD09IjEiIHwgcm91bmQ9PSIzIikgCmJhc2VsaW5lRnJhY3R1cmUxIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVCYXNlbGluZSAlPiUgZmlsdGVyKHJvdW5kPT0iMSIpCmJhc2VsaW5lRnJhY3R1cmUyIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVCYXNlbGluZSAlPiUgZmlsdGVyKHJvdW5kPT0iMyIpCmJhc2VsaW5lRnJhY3R1cmUxJGZyYWN0dXJlMSA8LSBiYXNlbGluZUZyYWN0dXJlMSRmcmFjdHVyZQpiYXNlbGluZUZyYWN0dXJlMiRmcmFjdHVyZTIgPC0gYmFzZWxpbmVGcmFjdHVyZTIkZnJhY3R1cmUKIyMgQmVsb3cgb25seSBjb21iaW5lcyBpZiB0ZWFtcyBhcmUgaW4gYm90aCByb3VuZCAxICYgMyB0b2dldGhlcjogCgojIyBUcmVhdG1lbnQ6IApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50IDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUgJT4lIApmaWx0ZXIocmVzdWx0cy5jb25kaXRpb249PSJ0cmVhdG1lbnQiKQp0cmVhdG1lbnRGcmFjdHVyZTEgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkEiKQp0cmVhdG1lbnRGcmFjdHVyZTIgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkFwIikKdHJlYXRtZW50RnJhY3R1cmUgPC0gY2JpbmQodHJlYXRtZW50RnJhY3R1cmUxLCB0cmVhdG1lbnRGcmFjdHVyZTIpCgojIyBDb250cm9sOiAgCmdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVDb250cm9sIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUgJT4lIAogIGZpbHRlcihyZXN1bHRzLmNvbmRpdGlvbj09ImNvbnRyb2wiKSAKY29udHJvbEZyYWN0dXJlMSA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlQ29udHJvbCAlPiUgZmlsdGVyKGNvbmRpdGlvbj09IkEiKQpjb250cm9sRnJhY3R1cmUyIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVDb250cm9sICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQXAiKQpjb250cm9sRnJhY3R1cmUgPC0gY2JpbmQoY29udHJvbEZyYWN0dXJlMSwgY29udHJvbEZyYWN0dXJlMikKCiMjIE1hbmlwdWxhdGlvbiBjaGVjazogCiMjIFVzZSBpbmRpdmlkdWFsIHByb3BvcnRpb24gZGF0YSBmcmFtZSBiL2Mgd2UncmUgaW50ZXJlc3RlZCBpbiBsb29raW5nIGF0IGluZGl2aWR1YWxzIHRoYXQgd2VyZSBpbiB0ZWFtcyA+bj0xCnRlYW1QYXR0ZXJucyA8LSAiVGVhbSAxIGFuZCBUZWFtIDJ8VGVhbSAxIGFuZCBUZWFtIDN8VGVhbSAyIGFuZCBUZWFtIDMiCmluZGl2aWR1YWxQcm9wb3J0aW9uJG1hbmlwdWxhdGlvbkFuc3dlcktleSA8LSBzdHJfZXh0cmFjdChpbmRpdmlkdWFsUHJvcG9ydGlvbiRyZXN1bHRzLm1hbmlwdWxhdGlvbkNoZWNrLHRlYW1QYXR0ZXJucykgCmluZGl2aWR1YWxQcm9wb3J0aW9uJG1hbmlwdWxhdGlvbkFuc3dlcnMgPC0gaW5kaXZpZHVhbFByb3BvcnRpb24kcmVzdWx0cy5tYW5pcHVsYXRpb24KaW5kaXZpZHVhbFByb3BvcnRpb24kcmVzdWx0cy5jb25kaXRpb24gPSB1bmxpc3QoaW5kaXZpZHVhbFByb3BvcnRpb24kcmVzdWx0cy5jb25kaXRpb24pCiMjIE9taXQgTkFzIGFuZCByZXN1bHRzIHRoYXQgY2FuJ3QgYmUgcHJvY2Vzc2VkOiAKY2xlYW5NYW5pcHVsYXRpb24gPC0gaW5kaXZpZHVhbFByb3BvcnRpb25bd2l0aChpbmRpdmlkdWFsUHJvcG9ydGlvbiwgZ3JlcGwodGVhbVBhdHRlcm5zLCBtYW5pcHVsYXRpb25BbnN3ZXJzKSAmIGdyZXBsKHRlYW1QYXR0ZXJucywgbWFuaXB1bGF0aW9uQW5zd2VyS2V5KSksXQojIyBUcmFuc2Zvcm0gaW50byBjb21wYXRpYWJsZSBmb3JtOiAKY2xlYW5NYW5pcHVsYXRpb24kbWFuaXB1bGF0aW9uQW5zd2VycyA9IHVubGlzdChjbGVhbk1hbmlwdWxhdGlvbiRtYW5pcHVsYXRpb25BbnN3ZXJzKQpgYGAKCiMjIFNlY3Rpb24gIzE6IERvZXMgZnJhY3R1cmUgaGF2ZSBjb250aW51aXR5IHdpdGggcHJpb3IgbWVhc3VyZXM/CgojIyAxQTogUmVwb3J0IHRoZSAlIG9mIGNvcnJlY3QgZ3Vlc3NlcyBvbiB0aGUgbWFuaXB1bGF0aW9uIGNoZWNrOiAKYGBge3J9CiMjIFRyZWF0bWVudCBtYW5pcHVsYXRpb246IAp0cmVhdG1lbnRNYW5pcHVsYXRpb24gPC0gY2xlYW5NYW5pcHVsYXRpb24gJT4lIGdyb3VwX2J5KGlkLCByZXN1bHRzLmNvbmRpdGlvbiwgbWFuaXB1bGF0aW9uQW5zd2VycywgbWFuaXB1bGF0aW9uQW5zd2VyS2V5KSAlPiUgZmlsdGVyKHJlc3VsdHMuY29uZGl0aW9uPT0idHJlYXRtZW50IikgJT4lIAogIHN1bW1hcmlzZShuPW4oKSkgCiMjIElmIHVzZXIgbWFuaXB1bGF0aW9uIGFuc3dlcnMgPT0gbWFuaXB1bGF0aW9uIGFuc3dlciBrZXkgdGhlbiBhZGQgMSAKdHJlYXRtZW50TWFuaXB1bGF0aW9uJGNvcnJlY3RBbnN3ZXJzIDwtIHN1bShpZmVsc2UodHJlYXRtZW50TWFuaXB1bGF0aW9uJG1hbmlwdWxhdGlvbkFuc3dlcnM9PXRyZWF0bWVudE1hbmlwdWxhdGlvbiRtYW5pcHVsYXRpb25BbnN3ZXJLZXksMSwwKSkKIyMgQ2FsY3VsYXRlIHBlcmNlbnQgb2YgY29ycmVjdCBtYW5pcHVsYXRpb24gYW5zd2VycyBmb3IgdHJlYXRtZW50OiAKdHJlYXRtZW50TWFuaXB1bGF0aW9uIDwtIHRyZWF0bWVudE1hbmlwdWxhdGlvbiAlPiUgbXV0YXRlKHBlcmNlbnRDb3JyZWN0ID0gKGNvcnJlY3RBbnN3ZXJzLyhucm93KHRyZWF0bWVudE1hbmlwdWxhdGlvbikpKSkKCiMjIENvbnRyb2wgbWFuaXB1bGF0aW9uOiAKY29udHJvbE1hbmlwdWxhdGlvbiA8LSBjbGVhbk1hbmlwdWxhdGlvbiAlPiUgZ3JvdXBfYnkoaWQsIHJlc3VsdHMuY29uZGl0aW9uLCBtYW5pcHVsYXRpb25BbnN3ZXJzLCBtYW5pcHVsYXRpb25BbnN3ZXJLZXkpICU+JSBmaWx0ZXIocmVzdWx0cy5jb25kaXRpb249PSJjb250cm9sIikgJT4lIAogIHN1bW1hcmlzZShuPW4oKSkgCiMjIElmIHVzZXIgbWFuaXB1bGF0aW9uIGFuc3dlcnMgPT0gbWFuaXB1bGF0aW9uIGFuc3dlciBrZXkgdGhlbiBhZGQgMSAKY29udHJvbE1hbmlwdWxhdGlvbiRjb3JyZWN0QW5zd2VycyA8LSBzdW0oaWZlbHNlKGNvbnRyb2xNYW5pcHVsYXRpb24kbWFuaXB1bGF0aW9uQW5zd2Vycz09Y29udHJvbE1hbmlwdWxhdGlvbiRtYW5pcHVsYXRpb25BbnN3ZXJLZXksMSwwKSkKIyMgQ2FsY3VsYXRlIHBlcmNlbnQgb2YgY29ycmVjdCBtYW5pcHVsYXRpb24gYW5zd2VycyBmb3IgY29udHJvbDogCmNvbnRyb2xNYW5pcHVsYXRpb24gPC0gY29udHJvbE1hbmlwdWxhdGlvbiAlPiUgbXV0YXRlKHBlcmNlbnRDb3JyZWN0ID0gKGNvcnJlY3RBbnN3ZXJzLyhucm93KGNvbnRyb2xNYW5pcHVsYXRpb24pKSkpCiMjIFByb3BvcnRpb24gdGVzdCBjb21wYXJpbmcgdHJlYXRtZW50IG1hbmlwdWxhdGlvbiBwZXJjZW50IGNvcnJlY3Qgd2l0aCBjaGFuY2U6IApgYGAKCiMjIDFCOiBQcm9wb3J0aW9uIHRlc3QgY29tcGFyaW5nIHRyZWF0bWVudCBtYW5pcHVsYXRpb24gcGVyY2VudCBjb3JyZWN0IHdpdGggY2hhbmNlOiAKYGBge3J9CiMjIOKFkyB+IDMzJSA9IGNoYW5jZSwgfjQzID0gdHJlYXRtZW50IChGSUxMLUlOIEVBQ0ggVElNRSBZT1UgUlVOIFdJVEggTkVXIERBVEEhKQoKcHJvcE1hbmlwdWxhdGlvbiA8LSBwcm9wLnRlc3QoeCA9IGMoMzMsIDQzKSwgbiA9IGMoMTAwLCAxMDApKQpwcmludChwcm9wTWFuaXB1bGF0aW9uKQpgYGAKCiMjIDFDOiBMb2dpc3RpYyByZWdyZXNzaW9uIHByZWRpY3RpbmcgYmluYXJ5IGZyYWN0dXJlIG91dGNvbWUgZnJvbSB2aWFiaWxpdHkgc2NhbGVzOiAKYGBge3J9CiMjIFNwbGl0IGRhdGEgaW50byA2MCUgdHJhaW5pbmcgYW5kIDQwJSB0ZXN0aW5nIGRhdGEgc2V0cyB0byB0ZXN0IGhvdyB3ZWxsIHRoZSBtb2RlbCBwZXJmb3JtcyAKc2V0LnNlZWQoMTIzKQpncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlJGZyYWN0dXJlIDwtIGFzLm51bWVyaWMoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZSkgCnNhbXBsZSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIG5yb3coZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSksIHJlcGxhY2UgPSBULCBwcm9iID0gYygwLjYsMC40KSkKdHJhaW4gPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVtzYW1wbGUsIF0KdGVzdCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlWyFzYW1wbGUsIF0KCiMjIFNpbXBsZSBsb2dpc3RpYyByZWdyZXNzaW9uOiB3ZSB3aWxsIGZpdCBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgaW4gb3JkZXIgdG8gcHJlZGljdCAKIyMgdGhlIHByb2JhYmlsaXR5IG9mIGZyYWN0dXJlIGJhc2VkIG9uIGEgdGVhbSdzIGF2ZXJhZ2UgdmlhYmlsaXR5IHN1bTogCgptb2RlbDEgPC0gZ2xtKGZyYWN0dXJlIH4gbWVhbiwgZmFtaWx5ID0gImJpbm9taWFsIiwgZGF0YSA9IHRyYWluKQpzdW1tYXJ5KG1vZGVsMSkKCiMjIFRvIGFzc2VzcyB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gZGV2aWFuY2UsIGxvb2sgYXQgZGV2aWFuY2UgaW4gc3VtbWFyeSBvdXRwdXQsIGlmIAojIyBkZXZpYW5jZSA9PSBzdW0gb2Ygc3FhdXJlcyBpbiBsaW5lYXIgcmVncmVzc2lvbiwgbnVsbCBkZXZpYW5jZSA9PSBkaWZmZXJlbmNlIGJldHdlZW4gCiMjIGEgbW9kZWwgd2l0aCBvbmx5IHRoZSBpbnRlcmNlcHQgKCJubyBtZWFuIHByZWRpY3RvcnMiKSBhbmQgdGhlIGEgc2F0dXJhdGVkIG1vZGVsIAojIyBhIG1vZGVsIHdpdGggYSB0aGVvcmV0aWNhbGx5IHBlcmZlY3QgZml0LiBNb2RlbCBkZXZpYW5jZSAocmVzaWR1YWwgZGV2aWFuY2UpIHNob3VsZCBiZSBsb3dlciAKIyMgc21hbGwgdmFsdWVzID09IGJldHRlciBmaXQuIAoKdGlkeShtb2RlbDEpCiMjIENvZWZmaWNpZW50IGVzdGltdGVzIGZyb20gbG9nIHJlZ3Jlc3Npb24gY2hhcmFjdGVyaXplIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwcmVkaWN0b3IgYW5kIAojIyByZXNwb25zZSB2YXJpYWJsZSBvbiBhIGxvZy1vZGRzIHNjYWxlLCBzbyBiaW5hcnkgaW5jcmVhc2UgZnJvbSBubyBmcmFjdHVyZSAtIGZyYWN0dXJlIGNhbiBiZSBpbnRlcnByZXRlZCBhcyBhc3NvY2lhdGVkIHdpdGggYSBkZWNyZWFzZSBpbiBtZWFuIHZpYWJpbGl0eSBzdW0uIAoKIyMgTW9yZSBjb2VmZmljaWVudCBvdXRwdXQ6IG1lYXN1cmUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFuZCBhY2N1cmFjeSBvZiB0aGUgY29lZmZpY2VudDogCmNvbmZpbnQobW9kZWwxKQoKIyMgTWFraW5nIHByZWRpY3Rpb25zOiAKIyMgV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgZnJhY3R1cmUgZ2l2ZW4gdGhlIGZvbGxvd2luZyB0ZWFtIG1lYW4gdmlhYmlsaXR5IHNjb3JlczogZm9yIGV4YW1wbGUgcHVycG9zZXM6IDQwIGFuZCA2NTogCgpwcmVkaWN0KG1vZGVsMSwgZGF0YS5mcmFtZShtZWFuID0gYyg1MCwgNjUpKSwgdHlwZSA9ICJyZXNwb25zZSIpCgojIyBGcm9tIHRoZSBvdXRwdXQsIHdlIGNhbiBzZWUgdGhhdCB0aGUgcHJvYmFiaWxpdHkgb2YgZnJhY3R1cmUgZGVjcmVhc2VzIGJ5IH40MCUgd2hlbiBtZWFuIHZpYWJpbGl0eSBzdW0gaW5jcmVhc2VzIGZyb20gNDAgdG8gNjUuIAoKIyMgTW9kZWwgZXZhbHVhdGlvbiAmIGRpYWdub3N0aWNzOiAKIyMgSG93IHdlbGwgZG9lcyB0aGUgbW9kZWwgZml0IHRoZSBkYXRhPyBBbmQgaG93IGFjY3VyYXRlIGFyZSB0aGUgcHJlZGljdGlvbnMgb24gYW4gb3V0LW9mLXNhbXBsZSBkYXRhIHNldD8KCiMjIFJlc2lkdWwgYXNzZXNzbWVudDogCgptb2RlbDFfZGF0YSA8LSBhdWdtZW50KG1vZGVsMSkgJT4lIAogIG11dGF0ZShpbmRleCA9IDE6bigpKQoKZ2dwbG90KG1vZGVsMV9kYXRhLCBhZXMoaW5kZXgsIC5zdGQucmVzaWQsIGNvbG9yID0gbWVhbikpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC41KSArCiAgZ2VvbV9yZWZfbGluZShoID0gMykKCiMjIFZhbGlkYXRpb24gb2YgcHJlZGljdGVkIHZhbHVlczogCiMjIEhvdyB3ZWxsIGRvZXMgdGhlIG1vZGVsIHBlcmZvcm0gd2hlbiBwcmVkaWN0aW5nIHRoZSB0YXJnZXQgdmFyaWFibGUgb24gb3V0LW9mLXNhbXBsZSBvYnNlcnZhdGlvbnM/IAoKdGVzdC5wcmVkaWN0ZWQubTEgPC0gcHJlZGljdChtb2RlbDEsIG5ld2RhdGEgPSB0ZXN0LCB0eXBlID0gInJlc3BvbnNlIikKCiMjIENsYXNzaWZpY2F0aW9uIHBlcmZvcm1hbmNlIGZvciBlYWNoIG1vZGVsIG9uIHRoZSB0ZXN0IGRhdGEuIE91dHB1dCBnaXZlcyB1cyBhIGxpc3Qgb2YgdHJ1ZSAvIGZhbHNlIHBvc2l0aXZlczogCgpsaXN0KAogIG1vZGVsMSA9IHRhYmxlKHRlc3QkbWVhbiwgdGVzdC5wcmVkaWN0ZWQubTEgPiAwLjUpICU+JSBwcm9wLnRhYmxlKCkgJT4lIHJvdW5kKDMpKSAKCnRhYmxlKHRlc3QkbWVhbiwgdGVzdC5wcmVkaWN0ZWQubTEgPiAwLjUpCmBgYAojIyAxRDogR3JhcGggb2YgZnJhY3R1cmUvbm8gZnJhY3R1cmUgdnMuIG1lYW4vc3RkZXYgdmlhYmlsaXR5IHNjYWxlCgpgYGB7cn0KIyMgT3ZlcmFsbDogCmcgPC0gZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUsIGFlcyhmYWN0b3IoZnJhY3R1cmUpLCBtZWFuKSkgCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBmcmFjdHVyZSB2YWx1ZSB2cy4gbWVhbiB2aWFiaWxpdHkgc2NvcmU6IGZyYWN0dXJlID49MC41MCBhY3Jvc3MgYWxsIGNvbmRpdGlvbnMgKG49MikiLCAKICAgICAgIHg9IiIsCiAgICAgICB5PSJOdW1lcmljIHN1bSBvZiB2aWFiaWxpdHkgbWVhc3VyZXMgcXVlc3Rpb25zIChyYW5nZTogNy03MCkiKSAKCmBgYAoKYGBge3J9CiMjIEJ5IGNvbmRpdGlvbiArIGZvcm1hdDogCmcgPC0gZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUsIGFlcyhmYWN0b3IoZnJhY3R1cmUpLCBtZWFuKSkgCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBmcmFjdHVyZSB2YWx1ZSB2cy4gbWVhbiB2aWFiaWxpdHkgc2NvcmU6IGZyYWN0dXJlID49MC41MCAobj0yKSIsIAogICAgICAgeD0iIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmNvbmRpdGlvbikgCmBgYAoKYGBge3J9CmdncGxvdChkYXRhPWdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUsIGFlcyhmcmFjdHVyZSwgbWVhbikpICsgCiAgIGdlb21fcG9pbnQoKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIpICsgbGFicyhtYWluPSJTY2F0dGVycGxvdCBvZiBmcmFjdHVyZSB2YWx1ZSB2cy4gbWVhbiBmb3IgdGVhbSB2aWFiaWxpdHkgc3VtcyBhY3Jvc3MgYWxsIGNvbmRpdGlvbnMgKG49MikiKSArICBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKSAKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZyYWN0dXJlLCBtZWFuKSkgKyAKICAgZ2VvbV9wb2ludCgpICsKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBjb2wgPSAicmVkIikgKyBsYWJzKG1haW49IlNjYXR0ZXJwbG90IG9mIGZyYWN0dXJlIHZhbHVlIHZzLiBtZWFuIGZvciB0ZWFtIHZpYWJpbGl0eSBzdW1zIChuPTIpIikgKyAgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmNvbmRpdGlvbikgCmBgYAoKIyMgU2VjdGlvbiAjMjogSG93IG9mdGVuIGRvZXMgZnJhY3R1cmUgb2NjdXI/CgojIyAyQTogUChiaW5hcnkgZnJhY3R1cmUpIGhpc3RvZ3JhbSBvZiBmcmFjdHVyZSBwcm9wb3J0aW9uIChieSB0ZWFtKQpgYGB7cn0KIyMgRmlyc3QgbWFrZSBzdXJlIHlvdSd2ZSBtYWRlIEFCQyBjb25kaXRpb24KZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb24sIGFlcyhncm91cGVkUHJvcG9ydGlvbiRwcm9wKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShicmVha3M9c2VxKDAsIDEsIGJ5PTAuMjApLCAKICAgICAgICAgICAgICAgICBjb2w9InJlZCIsIAogICAgICAgICAgICAgICAgIGZpbGw9ImdyZWVuIiwgCiAgICAgICAgICAgICAgICAgYWxwaGE9LjIpICsgbGFicyh0aXRsZT0iRnJlcXVlbmN5IG9mIHRlYW0gZnJhY3R1cmUgcHJvcG9ydGlvbnMgYnkgY29uZGl0aW9uIGFuZCBwYXR0ZXJuIHNlcXVlbmNlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSJ0ZWFtIGZyYWN0dXJlIHByb3BvcnRpb24iLCB5PSJDb3VudCIpICsgZmFjZXRfZ3JpZChyZXN1bHRzLmNvbmRpdGlvbiB+IC4pIApgYGAKYGBge3J9CmdncGxvdChkYXRhPWdyb3VwZWRQcm9wb3J0aW9uLCBhZXMoZ3JvdXBlZFByb3BvcnRpb24kcHJvcCkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzPXNlcSgwLCAxLCBieT0wLjIwKSwgCiAgICAgICAgICAgICAgICAgY29sPSJyZWQiLCAKICAgICAgICAgICAgICAgICBmaWxsPSJncmVlbiIsIAogICAgICAgICAgICAgICAgIGFscGhhPS4yKSArIGxhYnModGl0bGU9IkZyZXF1ZW5jeSBvZiB0ZWFtIGZyYWN0dXJlIHByb3BvcnRpb25zIGJ5IGNvbmRpdGlvbiBhbmQgcGF0dGVybiBzZXF1ZW5jZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0idGVhbSBmcmFjdHVyZSBwcm9wb3J0aW9uIiwgeT0iQ291bnQiKSArIGZhY2V0X2dyaWQocmVzdWx0cy5jb25kaXRpb24gfiBjb25kaXRpb24pICAKYGBgCgpgYGB7cn0KbGlicmFyeShNQVNTKSAgICAgCgojIyBUZXN0IGlmIHdoZXRoZXIgZnJhY3R1cmUgc21va2luZyBoYWJpdCBpcyBpbmRlcGVuZGVudCBvZiBjb25kaXRpb24gYXQgLjA1IHNpZ25pZmljYW5jZSBsZXZlbDogCgpjaGkgPSB0YWJsZShncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlJGZyYWN0dXJlLCBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlJHJlc3VsdHMuY29uZGl0aW9uKSAgCmNoaQpwcmludChjaGlzcS50ZXN0KGNoaSkpIApgYGAKCiMjIDJCOiBXaGF0J3MgdGhlIG92ZXJhbGwgJSBvZiBmcmFjdHVyaW5nIHRoZSBzZWNvbmQgdGltZT8gKGJ5IGNvbmRpdGlvbikKYGBge3J9CiMjIEZpbHRlcmluZyBzZWNvbmQgdGltZSBvbmx5OiAKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZSA8LSBhcy5udW1lcmljKGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUkZnJhY3R1cmUpCgojIyBUTy1ETzogcmV2aWV3IGJlbG93IGNvZGUsIHdvcnJpZWQgaXQncyBpbmNvcnJlY3Q6IAoKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVNlY29uZCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlICU+JSBncm91cF9ieShyZXN1bHRzLmNvbmRpdGlvbikgJT4lIAogICAgICBmaWx0ZXIoY29uZGl0aW9uPT0iQXAiKSAlPiUgCiAgICAgIG11dGF0ZShvdmVyYWxsUGVyY2VudCA9IHN1bShhcy5udW1lcmljKGZyYWN0dXJlKSkpICU+JSAKICAgICAgc3VtbWFyaXNlKG49bigpLCBvdmVyYWxsUGVyY2VudD11bmlxdWUob3ZlcmFsbFBlcmNlbnQpL24pIApwcmludChncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlU2Vjb25kKQoKIyMgRm9yIGJhc2VsaW5lIHRoZW9yZXRpY2FsIGRpc3RyaWJ1dGlvbjogKHRvLWRvOiBsb29rIG92ZXIgdGhpcywgd29ycmllZCBhbHNvIHRoYXQgaXQncyB3cm9uZykKCmdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVTZWNvbmRCYXNlIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVCYXNlbGluZSAlPiUgCiAgICAgIGZpbHRlcihyb3VuZD09IjMiKSAlPiUgCiAgICAgIHN1bW1hcmlzZShuPW4oKSwgb3ZlcmFsbFBlcmNlbnQ9c3VtKGFzLm51bWVyaWMoZnJhY3R1cmUpKS9uKSAKcHJpbnQobWVhbihncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlU2Vjb25kQmFzZSRvdmVyYWxsUGVyY2VudCkpCgojIyBTZXQtdXAgc2VwYXJhdGUgZ3JvdXBzIGZvciBwcm9wb3J0aW9uIHRlc3RzIHRvIGFuc3dlcjogZG9lcyB1bm1hc2tlZCBmcmFjdHVyZSBtb3JlL2xlc3MgdGhhbiBtYXNrZWQsIGFuZCBtb3JlL2xlc3MgdGhhbiBuZXcgcGFpcnM/IAoKIyMgQ29udHJvbDogCiMjIFByb3BvcnRpb24gdGVzdHMgZm9yIGVhY2ggKFRPLURPLCBmaWd1cmUgb3V0IGFyZ3VtZW50IHN0dWZmOiB0aGlzIGRvZXNuJ3Qgc2VlbSBsaWtlIHRoZSByaWdodCB0ZXN0IHRvIHJ1biBmb3IgdGhlIHF1ZXN0aW9uIHdlJ3JlIGFza2luZz8pIGFsc28sIGZpbGwtdGhpcyBpbiBldmVyeSB0aW1lIHlvdSBnZXQgbmV3IGRhdGE6IAoKIyMgSXMgdGhlIHByb3BvcnRpb24gb2YgZnJhY3R1cmUgaW4gdGhlIHNlY29uZCByb3VuZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBpbiB0aGUgdHdvIGNvbmRpdGlvbnMgKGkuZS4gdHJlYXRtZW50ICsgYmFzZWxpbmUpIAp0cmVhdG1lbnR2c0Jhc2VsaW5lQ2hhbmdlIDwtIGMoNDgsIDQ5KQpwcm9wRnJhY3R1cmVDaGFuZ2VUcmVhdG1lbnR2c0Jhc2UgPC0gcHJvcC50ZXN0KHggPSBjKHRyZWF0bWVudHZzQmFzZWxpbmVDaGFuZ2UpLCBuID0gYygxMDAsIDEwMCkpCnByaW50KHByb3BGcmFjdHVyZUNoYW5nZVRyZWF0bWVudHZzQmFzZSkgCgojIyBJcyB0aGUgcHJvcG9ydGlvbiBvZiBmcmFjdHVyZSBpbiB0aGUgc2Vjb25kIHJvdW5kIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGluIHRoZSB0d28gY29uZGl0aW9ucyAoaS5lLiBjb250cm9sICsgYmFzZWxpbmUpIApjb250cm9sdnNCYXNlbGluZUNoYW5nZSA8LSBjKDQwLCA0OSkKcHJvcEZyYWN0dXJlQ2hhbmdlQ29udHJvbHZzQmFzZSA8LSBwcm9wLnRlc3QoeCA9IGMoY29udHJvbHZzQmFzZWxpbmVDaGFuZ2UpLCBuID0gYygxMDAsIDEwMCkpCnByaW50KHByb3BGcmFjdHVyZUNoYW5nZUNvbnRyb2x2c0Jhc2UpCmBgYAojIyBTZWN0aW9uIDM6IEhvdyBjb25zaXN0ZW50IGlzIGZyYWN0dXJlPyAKCiMjIDNBOiBjYWxjdWxhdGluZyB0aGUgY29uZGl0aW9uYWwgcHJvYmFiaWxpdGllcyBvZiBmcmFjdHVyZSBmb3IgZWFjaCBjb25kaXRpb246IApgYGB7cn0KCiMjIElmIGZyYWN0dXJlZCB0aGUgZmlyc3QgdGltZSwgd2hhdCdzIHRoZSAlIG9mIGZyYWN0dXJpbmcgdGhlIHNlY29uZCB0aW1lPyBsb29rIGF0IDEgYW5kIEFwIGNvbWJpbmF0aW9uIGZvciAlIGluIHNlY29uZCB0aW1lOiAKCiMjIENvbXBhcmUgYm90aCB0cmVhdG1lbnQgYW5kIGNvbnRyb2wgd2l0aCBiYXNlbGluZSBhcyB0aGVvcmV0aWNhbCBkaXN0cmlidXRpb246IAoKIyMgQ29uZGl0aW9uYWwgcHJvYmFiaWxpdHkgZm9yIG1hc2tlZDogCiMgb2YgZ3JvdXBzIHdobyBmcmFjdHVyZWQgMSBhbmQgMgp0cmVhdG1lbnRGcmFjdHVyZTEyIDwtIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0iMSIgJiB0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmU9PSIxIiwxLDApKS9ucm93KHRyZWF0bWVudEZyYWN0dXJlKQojIG9mIGdyb3VwcyB3aG8gZnJhY3R1cmVkIG9ubHkgMQp0cmVhdG1lbnRGcmFjdHVyZU9ubHkxIDwtIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0iMSIgJiB0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmU9PSIwIiwxLDApKS9ucm93KHRyZWF0bWVudEZyYWN0dXJlKSAKIyBvZiBncm91cHMgd2hvIGZyYWN0dXJlZCBvbmx5IDIKdHJlYXRtZW50RnJhY3R1cmVPbmx5MiA8LSBzdW0oaWZlbHNlKHRyZWF0bWVudEZyYWN0dXJlMSRmcmFjdHVyZT09IjAiICYgdHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlPT0iMSIsMSwwKSkvbnJvdyh0cmVhdG1lbnRGcmFjdHVyZSkKIyBvZiBncm91cHMgd2hvIGZyYWN0dXJlZCBuZXZlciAgICAgICAgCnRyZWF0bWVudEZyYWN0dXJlTmV2ZXIgPC0gc3VtKGlmZWxzZSh0cmVhdG1lbnRGcmFjdHVyZTEkZnJhY3R1cmU9PSIwIiAmIHRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZT09IjAiLDEsMCkpL25yb3codHJlYXRtZW50RnJhY3R1cmUpCmNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCA8LSBtYXRyaXgoYyh0cmVhdG1lbnRGcmFjdHVyZTEyLCB0cmVhdG1lbnRGcmFjdHVyZU9ubHkxLCB0cmVhdG1lbnRGcmFjdHVyZU9ubHkyLCB0cmVhdG1lbnRGcmFjdHVyZU5ldmVyKSxuY29sPTIsYnlyb3c9VFJVRSkKY29sbmFtZXMoY29uZGl0aW9uYWxQcm9iVHJlYXRtZW50KSA8LSBjKCJBcCBmcmFjIiwiQXAgbm8gZnJhYyIpIApyb3duYW1lcyhjb25kaXRpb25hbFByb2JUcmVhdG1lbnQpIDwtIGMoIkEgZnJhYyIsIkEgbm8gZnJhYyIpCmNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCA8LSBhcy50YWJsZShjb25kaXRpb25hbFByb2JUcmVhdG1lbnQpCmNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudAoKIyMgQ29uZGl0aW9uYWwgcHJvYWJpbGl0eSBmb3IgdW5tYXNrZWQ6IAojIG9mIGdyb3VwcyB3aG8gZnJhY3R1cmVkIDEgYW5kIDIKY29udHJvbEZyYWN0dXJlMTIgPC0gc3VtKGlmZWxzZShjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlPT0iMSIgJiBjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlPT0iMSIsMSwwKSkvbnJvdyhjb250cm9sRnJhY3R1cmUpCiMgb2YgZ3JvdXBzIHdobyBmcmFjdHVyZWQgb25seSAxCmNvbnRyb2xGcmFjdHVyZU9ubHkxIDwtIHN1bShpZmVsc2UoY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZT09IjEiICYgY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZT09IjAiLDEsMCkpL25yb3coY29udHJvbEZyYWN0dXJlKSAKIyBvZiBncm91cHMgd2hvIGZyYWN0dXJlZCBvbmx5IDIKY29udHJvbEZyYWN0dXJlT25seTIgPC0gc3VtKGlmZWxzZShjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlPT0iMCIgJiBjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlPT0iMSIsMSwwKSkvbnJvdyhjb250cm9sRnJhY3R1cmUpCiMgb2YgZ3JvdXBzIHdobyBmcmFjdHVyZWQgbmV2ZXIgICAgICAgIApjb250cm9sRnJhY3R1cmVOZXZlciA8LSBzdW0oaWZlbHNlKGNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmU9PSIwIiAmIGNvbnRyb2xGcmFjdHVyZTIkZnJhY3R1cmU9PSIwIiwxLDApKS9ucm93KGNvbnRyb2xGcmFjdHVyZSkKY29uZGl0aW9uYWxQcm9iQ29udHJvbCA8LSBtYXRyaXgoYyhjb250cm9sRnJhY3R1cmUxMiwgY29udHJvbEZyYWN0dXJlT25seTEsIGNvbnRyb2xGcmFjdHVyZU9ubHkyLCBjb250cm9sRnJhY3R1cmVOZXZlciksbmNvbD0yLGJ5cm93PVRSVUUpCmNvbG5hbWVzKGNvbmRpdGlvbmFsUHJvYkNvbnRyb2wpIDwtIGMoIkFwIGZyYWMiLCJBcCBubyBmcmFjIikgCnJvd25hbWVzKGNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCkgPC0gYygiQSBmcmFjIiwiQSBubyBmcmFjIikKY29uZGl0aW9uYWxQcm9iQ29udHJvbCA8LSBhcy50YWJsZShjb25kaXRpb25hbFByb2JDb250cm9sKQpjb25kaXRpb25hbFByb2JDb250cm9sCmBgYAoKIyMgM0I6IE5vdyBpbnZlc3RpZ2F0aW5nIHRoZSBiaWcgcmVzdWx0OiBzd2l0Y2ggJTogd2hhdCdzIHRoZSAlIG9mIHBhaXJzIGZsaXBwaW5nIHRoZWlyIGRlY2lzaW9ucz8KCmBgYHtyfQojIyBDb252ZXJ0IGZvcm1hdCBiZWZvcmUgbWVyZ2U6ICp0aGlzIGNhbiBiZSBzaW1wbGlmaWVkKjogCgp0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmUgPC0gYXMubnVtZXJpYyh0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmUpIAp0cmVhdG1lbnRGcmFjdHVyZTEkZnJhY3R1cmUgPC0gYXMubnVtZXJpYyh0cmVhdG1lbnRGcmFjdHVyZTEkZnJhY3R1cmUpIAp0cmVhdG1lbnRGcmFjdHVyZSRhYnNGcmFjdHVyZSA8LSBhYnModHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlLXRyZWF0bWVudEZyYWN0dXJlMSRmcmFjdHVyZSkKCmNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmUgPC0gYXMubnVtZXJpYyhjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlKQpjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZSkKY29udHJvbEZyYWN0dXJlJGFic0ZyYWN0dXJlIDwtIGFicyhjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlLWNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmUpCgojIGJhc2VsaW5lRnJhY3R1cmUkZnJhY3R1cmUxIDwtIGFzLm51bWVyaWMoYmFzZWxpbmVGcmFjdHVyZSRmcmFjdHVyZTEpIAojIGJhc2VsaW5lRnJhY3R1cmUkZnJhY3R1cmUyIDwtIGFzLm51bWVyaWMoYmFzZWxpbmVGcmFjdHVyZSRmcmFjdHVyZTIpIAojIGJhc2VsaW5lRnJhY3R1cmUkYWJzRnJhY3R1cmUgPC0gYWJzKGJhc2VsaW5lRnJhY3R1cmUkZnJhY3R1cmUxLWJhc2VsaW5lRnJhY3R1cmUkZnJhY3R1cmUyKQoKIyMgUmVzdWx0cyBoZXJlIHNlZW0gZmlzaHk/IFRyaXBsZSBjaGVjayBteSBjb2RlIGZvciBhYnMvc3VtPyAKCnRyZWF0bWVudEZyYWN0dXJlQWJzU3VtIDwtIHN1bSh0cmVhdG1lbnRGcmFjdHVyZSRhYnNGcmFjdHVyZSkgCnByaW50KHRyZWF0bWVudEZyYWN0dXJlQWJzU3VtKQpjb250cm9sRnJhY3R1cmVBYnNTdW0gPC0gc3VtKGNvbnRyb2xGcmFjdHVyZSRhYnNGcmFjdHVyZSkKcHJpbnQoY29udHJvbEZyYWN0dXJlQWJzU3VtKQojIyBiYXNlbGluZUZyYWN0dXJlQWJzU3VtIDwtIHN1bShiYXNlbGluZUZyYWN0dXJlJGFic0ZyYWN0dXJlKSAKCiMjIERvbid0IHdlIHdhbnQgYSBwcm9wb3J0aW9uIHRlc3QgaGVyZSBiZWZvcmUgYWRkaW5nIC8gdHJ5aW5nIGNoaS1zcXVhcmVkPyAKCnRyZWF0bWVudEFic0NoYW5nZT1jKCkgCmNvbnRyb2xBYnNDaGFuZ2U9YygpCgojIyBVc2luZyBiYXNlbGluZSBhcyB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gCiMjIFRyZWF0bWVudDogCmNoaXNxLnRlc3QodHJlYXRtZW50QWJzQ2hhbmdlLHA9YmFzZWxpbmVBYnNDaGFuZ2UpCgojIyBDb250cm9sOgpjaGlzcS50ZXN0KGNvbnRyb2xBYnNDaGFuZ2UscD1iYXNlbGluZUFic0NoYW5nZSkKYGBgCgojIyBWaXN1YWxpemluZyBjaGFuZ2U6IAoKYGBge3J9CiMjIFZpc3VhbGl6ZSBkaWZmZXJlbmNlczogCm5vcm1hbGl6ZWRUcmVhdG1lbnRDaGFuZ2UgPC0gdHJlYXRtZW50RnJhY3R1cmVBYnNTdW0vbnJvdyh0cmVhdG1lbnRGcmFjdHVyZSkKbm9ybWFsaXplZENvbnRyb2xDaGFuZ2UgPC0gY29udHJvbEZyYWN0dXJlQWJzU3VtL25yb3coY29udHJvbEZyYWN0dXJlKQoKZGF0IDwtIGRhdGEuZnJhbWUoY2hhbmdlc1BlckNvbmRpdGlvbj0gZmFjdG9yKGMoIk5vcm1hbGl6ZWQgcGVyY2VudGFnZSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gbWFza2VkID49LjUwIiwiTm9ybWFsaXplZCBwZXJjZW50YWdlIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiB1bm1hc2tlZCA+PS41MCIpLCBsZXZlbHM9YygiTm9ybWFsaXplZCBwZXJjZW50YWdlIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiBtYXNrZWQgPj0uNTAiLCJOb3JtYWxpemVkIHBlcmNlbnRhZ2Ugb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHVubWFza2VkID49LjUwIikpLAogICAgICAgICAgICAgICAgICBmcmFjdHVyZVZhbHVlU3dpdGNoID0gYyhub3JtYWxpemVkVHJlYXRtZW50Q2hhbmdlLCBub3JtYWxpemVkQ29udHJvbENoYW5nZSkpCgpwIDwtIGdncGxvdChkYXRhPWRhdCwgYWVzKHg9Y2hhbmdlc1BlckNvbmRpdGlvbiwgeT1mcmFjdHVyZVZhbHVlU3dpdGNoKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKcCA8LSBnZ3Bsb3RseShwKQpwCmBgYAoKCgoKCgoKCg==